
<head>
</head>
<html>
<body>
  <canvas id=drw width="1200" height="600"></canvas>
<script>

var micros=Date.now;
var c = document.getElementById("drw");
var ctx = c.getContext("2d");
zprintf=console.log;
function PSTR(x){return x;}
var float=parseFloat;
function fmax(a,b){return (a>=b)?a:b;}
function fmin(a,b){return (a>=b)?b:a;}
function InvSqrt(f) {return 1.0/Math.sqrt(f);}
var cbrt=Math.cbrt;
var sqrt=Math.sqrt;
var fabs=Math.abs;
function cube(x){return x*x*x;}
var cinv;
function xInvSqrt(n) {return stepdiv2*(n>0.05?(cinv=InvSqrt(n)):(cinv=0.5));}
function zInvSqrt(n) {return stepdiv2/n;}
//function xInvSqrt(n) {return Math.round(Math.sqrt(n));}

var vv=[];
var ddd=[];
var CLOCKCONSTANT=1000000;
var STEPFREQ=50000;
var STEPCLOCK=Math.round(CLOCKCONSTANT/STEPFREQ);
var rampv=1;
var head=0;
var tail=0;
var NUMBUFFER=40;
var move=[];
var isG0;
var m;
var f=0;
var x1=0;
var y1=0;
var z1=0;
var e1=0;
var maxf=[100,100,100,100];
var stepmm=100;
var accel=50;
var tjerk=200;  // true jerk
var ajerk;
var zaccel=accel;
var mvaccel=accel;
var xyjerk=5;
var vjerk=10;
var zjerk=xyjerk;
var labs=Math.abs;
var fabs=Math.abs;

var laxis;
var fastaxis;
var totalstep;
var oacup,acup;
var oacdn,acdn;
var ta;
var stepdiv,stepdiv2;
var nextmicros;
var rampup,rampdown;
var mctr2;
var nextdly;
var ldelay=0;

var dlp=0;
var cmd0=0;
var cmddelay=[0];
var cmdhead=0;
var cmdtail=0;
var lastmm=[0,0,0,0,0];
var currmm=[0,0,0,0,0];
var mmdis=[0,0,0,0,0];
var mcx=[0,0,0,0];
var bsdx=[0,0,0,0];
var sx=[0,0,0,0];

/// command buffer
var NUMCMDBUF=100000;
function nextbuffm(x) {return ((x) < NUMCMDBUF-1 ? (x) + 1 : 0);}
for (var i=0;i<NUMBUFFER;i++){move.push({});}
//for (var i=0;i<NUMCMDBUF;i++){cmddelay.push(0);}

var cmhead = 0;
var cmtail = 0;
var cmcmd;
var cmbit = 0;
var cmdlaserval = 0;

var mo = 0;
function cmdfull() {return nextbuffm(cmhead)==cmtail;}
function cmdnotfull() {return nextbuffm(cmhead)!=cmtail;}
function cmdempty () {return cmhead==cmtail;}

var nextok = 0;
var laserwason = 0;

var sendwait = 0;

var maincmdlaserval = 0;

function pushcmd()
{


  // if move cmd, and no motor move, save the delay
  if ( (cmd0 & 1) && !(cmd0 & (15 << 1))) {
    ldelay += cmd0 >> 5;
  } else {
    cmhead = nextbuffm(cmhead);
    if (cmd0 & 1)cmd0 += (ldelay << 5);
    //cmddelay[cmhead] = cmd0;
    cmddelay.push(cmd0);
	ddd.push(cmd0 >> 5);
    ldelay = 0;
  }

}

function newdircommand(laserval)
{
  // change dir command
  //cmd0 = 0;//DIRDELAY << 6;
  cmd0 = (laserval << 9);
  if (sx[0] > 0)cmd0 |= 2;
  if (sx[1] > 0)cmd0 |= 8;
  if (sx[2] > 0)cmd0 |= 32;
  if (sx[3] > 0)cmd0 |= 128;
  // TO know whether axis is moving
  if (bsdx[0] > 0)cmd0 |= 4;
  if (bsdx[1] > 0)cmd0 |= 16;
  if (bsdx[2] > 0)cmd0 |= 64;
  if (bsdx[3] > 0)cmd0 |= 256;
  ldelay = 0;
  pushcmd();

}



function bufflen() {return  head >= tail ? head - tail : (NUMBUFFER + head) - tail;} // 5+0 - 4

function nextbuff(x) {return (x) < NUMBUFFER-1 ? (x) + 1 : 0;}
function prevbuff(x) {return ((x) > 0 ? (x) - 1 : NUMBUFFER-1);}
function copy(a,b){
  for (var i=0;i<b.length;i++){
    a[i]=b[i];
  }
}

function int(x){return Math.floor(x);}
function max(a,b){return (a>=b)?a:b;}
function min(a,b){return (a<=b)?a:b;}
function abs(a){return Math.abs(a);}
var sqrt=Math.sqrt;
function sqr2(x){return x*x;}




var MINCORNERSPEED=1;
var lastf=0;
var curru=[0,0,0,0,0];
var prevu=[0,0,0,0,0];
var tailok=0;
var rampup=0;
var rampdown=0;


function FASTAXIS(m){
	return (m.status >> 4)&3;
}

/*
S = (v * Math.sqrt(v) /jerk )

s = 	s0 + v0t + 1/2a0t2 + 1/6jt3
	 Notes: Ar = (Jm*T)/4					Ar is ramp acceleration
 *			T  = 2*sqrt((Vf-Vi)/Jm)			T is time
 *
 
 Ar = Jm*(2*sqrt((Vf-Vi)/Jm)/4
*/


function ramplenq(v0,v1,stepa) {
  if (v1>v0)return (v1-v0)*stepa;
  return 0;
}
function speedat(v0,a,s) {
    return (a * s  + v0);
}

var lastac=0;
var nextac=0;
var currac=0;
var fe=0;
var rampupmm,rampdownmm;
function prepareramp(bpos)
{
	// local m
    var m = move[bpos];

    faxis = FASTAXIS(m);
    ytotalstep = abs(m.dx[faxis]);

    stepa = 1.0 / (m.ac);
	nextac=0;
    if (bpos!=(head)) {
        next=move[nextbuff(bpos)];
        fe=next.fs;
		if (m.fn>next.fn)nextac=-1;
		if (m.fn<next.fn)nextac=+1;
		
    } else fe=0;

    ru=ramplenq(m.fs, m.fn, stepa);
    rd=ramplenq(fe, m.fn, stepa);

    if (ru+rd>m.dis) {
        // if crossing and have rampup
		r = ((ru + rd) - m.dis) / 2;
		ru -= r;
		rd -= r;
		if (ru < 0)ru = 0;
		if (rd < 0)rd = 0;
		if (rd > m.dis)rd = m.dis;
		if (ru > m.dis)ru = m.dis;
		m.fn = speedat(m.fs, m.ac, ru);
    }
    m.totalstep=ytotalstep;
	rampupmm=ru;
	rampdownmm=rd;
    m.status |= 4;
	
		
    console.log(m);
}


function backforward()
{
// now back planner
    h=head;//
    //h=prevbuff(head);
    if (h==tailok) {
        return 0;
    }

    var next;
    curr = move[h];
    curr.fs=min(curr.maxs,(curr.ac*curr.dis));
    h=prevbuff(h);

    while (h!=tailok) {
        next=curr;
        curr=move[h];
        if (curr.fs!=curr.maxs) {
            fs=next.fs+(curr.ac*curr.dis);
            if (fs<curr.maxs) {
                curr.fs=fs;
            } else {
                curr.fs=curr.maxs;
            }
        }
        h=prevbuff(h);
    }

// forward
    //h=nextbuff(tailok);
    //if (h==head) {
     //   return 0;
    //}
    h=tailok;
	
	next=move[h];
    h=nextbuff(h);
    while (h!=head) {
        curr=next;
        next=move[h];
        if (curr.fs<next.fs) {
            fs=curr.fs+(curr.ac*curr.dis);
            if (fs<next.fs) {
                next.fs=fs;
                tailok=prevbuff(h);
            }
            curr.fn=min(fs,curr.fn);
        }
        if (next.fs==next.maxs) tailok=prevbuff(h);
        h=nextbuff(h);
    }

}


function planner(h){
  curr=move[h];
  scale=1;
  xtotalstep=abs(curr.dx[curr.faxis]);
  copy(prevu,curru);
  curru[4] = 1;
  for (var i=0;i<4;i++){
    curru[i]=0;
    if (curr.dx[i]!=0){
      cdx = (curr.fn) * mmdis[i];
      if ((i != 3)) {
        scale2 = (maxf[i]) * curr.dis / fabs(cdx);
        if (scale2 < scale) scale = scale2;
      }
      // if Z then need to scale the acceleration too
      if (i == 2) {
        scalea = zaccel * curr.dis / fabs(curr.ac * mmdis[i]);
        if (scalea < 1)curr.ac *= scalea;
      }
      curru[i] = mmdis[i] / curr.dis;
    }
  }
  var ujerk = xyjerk * scale;
  scale *= curr.fn;
  curr.fn = (scale * scale);

  max_f = MINCORNERSPEED * MINCORNERSPEED;
  if (bufflen()>1) {

     var junc_cos = -prevu[0] * curru[0] - prevu[1] * curru[1] - prevu[2] * curru[2];
    if (junc_cos > 0.999999) {
      max_f = MINCORNERSPEED * MINCORNERSPEED;
    } else if (junc_cos < -0.999999) {
      max_f = 40000;
    } else {
      var sin_theta_d2 = sqrt(0.5 * (1.0 - junc_cos)); // Trig half angle identity. Always positive.
      max_f = fmax( 1, (ujerk * sin_theta_d2) / (1.0 - sin_theta_d2) );
    }


  }
  curr.maxs=min(curr.fn,lastf);
  curr.maxs=min(curr.maxs,max_f);
  lastf=curr.fn;
  backforward();
}

var lastx=0;
var lasty=0;

function addmove(fs,x2,y2,z2,e2,g0,rel) {
  
  var curr=move[nextbuff(head)];
  if (rel) {
    x2+=x1;
    y2+=y1;
    z2+=z1;
    e2+=e1;
  }
  copy(lastmm,currmm);
  currmm[0]=mmdis[0] = (x2 - x1);
  currmm[1]=mmdis[1] = (y2 - y1);
  currmm[2]=mmdis[2] = (z2 - z1);
  mmdis[3] = (e2 - e1);

  var dx=[];
  dx[0]=int(x2*stepmm)-int(x1*stepmm);
  dx[1]=int(y2*stepmm)-int(y1*stepmm);
  dx[2]=int(z2*stepmm)-int(z1*stepmm);
  dx[3]=int(e2*stepmm)-int(e1*stepmm);

  curr.dis = sqrt(sqr2(mmdis[0]) + sqr2(mmdis[1]) + sqr2(mmdis[2]));
  curr.dx=dx;
  
  dd=0;
  faxis=0;
  for (var i=0;i<4;i++){
    var d=Math.abs(dx[i]);
	if (d>dd){
      dd=d;
      faxis=i;
    }
  }

  head=nextbuff(head);
  curr.fn=fs;
  curr.fs=0;
  curr.status=g0?8:0;
  curr.x1=x1;
  curr.y1=y1;
  curr.z1=z1;
  curr.faxis=faxis;
  curr.status |= faxis << 4;
  curr.status|=1;
  curr.ac = 2 * (g0 ? mvaccel : accel);
  
  planner(head);
  x1=x2;
  y1=y2;
  z1=z2;
  e1=e2;


}
function calculate_delta_steps(){
  for (var i = 0; i < 4; i++) {


    if (m.dx[i] > 0) {
      bsdx[i] = (m.dx[i]);
      sx[i] = 1;
    } else {
      bsdx[i] = -(m.dx[i]);
      sx[i] = -1;
    }
  }
  var ff=max(fe,max(m.fs,m.fn)); // get fastest speed
  /*var u=xInvSqrt(ff)/STEPCLOCK;
  u=1.1;
  mctr = Math.round(totalstep*u) ;
  totalstep = mctr;
  acup /= u;
  acdn /= u;
  stepdiv2 /= u;
  stepdiv /= u;
  */
  mctr =totalstep; 
  newdircommand(!isG0 ? 255 : 0);
}
var jramp1,jramp2;
var jrampb1,jrampb2;


function speedatJ(Vi_squared, L, jerk)
{
	if (L==0)return Vi_squared;
	Vi=Math.sqrt(Vi_squared);
    // 0 iterations (a reasonable estimate)
	cbrt_jerk=Math.pow(Math.abs(jerk),0.3333333);
    var estimate = Math.pow(L, 0.66666666) * cbrt_jerk + Vi;
	///*
	// 1st iteration
    var L_squared = L*L;
    var J_z = ((estimate - Vi) * (Vi + estimate) * (Vi + estimate)) / L_squared - jerk;
    var J_d = (2*Vi*estimate - Vi_squared + 3*(estimate*estimate)) / L_squared;
    estimate = estimate - J_z/J_d;
    // 2nd iteration
    J_z = ((estimate - Vi) * (Vi + estimate) * (Vi + estimate)) / L_squared - jerk;
    J_d = (2*Vi*estimate - Vi_squared + 3*(estimate*estimate)) / L_squared;
    estimate = estimate - J_z/J_d;
    
	//*/
	return estimate*estimate;
}

function ramplenA(Vi,Vf,a) {
  return fabs(sqr(Vi)-sqr(Vf))*0.5/a;
}

function ramplenJ1(Vi, amax, jerk) 
{
		// my own version
		var t=fabs(amax/jerk);
		return Vi*t+jerk*t*t*t/6;
}


function ramplenJ(Vi,Vf,jerk){
	//return (Vi + Vf) * sqrt(fabs((Vf - Vi) *2/jerk));		// new formula
	return fabs(Vi-Vf) * sqrt(fabs((Vi-Vf) / jerk));		// old formula
}

function ramplenJ(Vi, Vf, jerk) 
{
		// my own version
		var t=sqrt(2*fabs((Vf-Vi)/jerk));
		return Vi*t+jerk*t*t*t/6;
}

function calc_jerk(deltaV,L){
	return(cube(deltaV / (Math.pow(L, 0.66666666))));
}
var c1;
function startmove()
{

    if ((head == tail)) {
        return 0;
    }
    t = nextbuff(tail);
    prepareramp(t);
	// global m
	m=move[t];
	isG0 = m.status & 8;

	laxis = fastaxis;
	fastaxis = FASTAXIS(m);
	totalstep = labs(m.dx[fastaxis]);
	var mmstep=m.dis/totalstep;


	// recalculate acceleration for up and down, to minimize rounding error
	acup = accel*2;
	acdn = -accel*2;
	// 24-4-2018
	// Now need to convert mm rampup to step rampup

	//m.fs = ta;
	ta = m.fs;
	/*
	first we need to know how much velocity reached from zero acceleration from start
	Vf = (sqrt(L)*(L/sqrt(1/Jm))^(1/6)+(1/Jm)^(1/4)*Vi)/(1/Jm)^(1/4)
	*/
	vjramp = 0.78*ramplenq(0,accel,0.5/tjerk);
	
	jramp1=0;
	jramp2=0;
	jrampb1=0;
	jrampb2=0;
	fnS=sqrt(m.fn);
	fsS=sqrt(m.fs);
	feS=sqrt(fe);
	//if (0){//
	jrampd=ramplenJ(fnS-vjramp,fnS,-tjerk);
	if (rampupmm){
		jrampu=ramplenJ(fsS,fsS+vjramp,tjerk);
		f1=m.fs;
		f2=m.fn;
		//jramp=0.5*rampupmm;
		
		if (lastac<=0){
			jramp1=fmin(jrampu,rampupmm*0.5); // jerk up from zero
		}				
		if (rampupmm<m.dis)jramp2=fmin(jrampd,rampupmm-jrampu); // jerk to cruise
		/*
		s = a * t²
		a = v / t
		s = v² / 2*a
		
		S = [V^2 / (2 * a)] + [(V * a) / (2 * J)]
		*/
		f1=speedatJ(m.fs,jramp1,tjerk);
		f2=fmin(m.fn,speedat(f1,m.ac,rampupmm-jramp1-jramp2));
		//acup = ((f2  - f1 )) / (rampupmm-jramp1-jramp2); //(fmax(1,m.rampup-acramp));
	}
	if (rampdownmm){
		jrampu=ramplenJ(feS+vjramp,feS,tjerk);
		f1=m.fn;
		f2=fe;
		//jramp=0.5*rampdownmm;
		if (nextac>=0){
			jrampb2=fmin(jrampu,rampdownmm*0.5); // jerk stop
		}				
		if (rampdownmm<m.dis)jrampb1=fmin(jrampd,rampdownmm-jrampu); // down from cruise

		f1=speedatJ(m.fn,jrampb1,-tjerk);
		f2=fmax(fe,speedat(f1,-m.ac,rampdownmm-jrampb1-jrampb2));
		//acdn = -((f1  - f2 )) / (rampdownmm-jrampb1-jrampb2); //(fmax(1,m.rampdown-acramp));
	}
	oacup = acup;
	oacdn = acdn;

	// STEP
	//ta = m.fs ;
	// this calculation cause
	//stepdiv = (CLOCKCONSTANT / (Cstepmmx(fastaxis)) );
	//stepdiv = (CLOCKCONSTANT / (Cstepmmx(fastaxis)) ) * Cstepmmx(fastaxis)*dis/(totalstep);

	stepdiv = CLOCKCONSTANT*mmstep;
	stepdiv2 = wstepdiv2 = stepdiv;
	m.status &= ~3;
	m.status |= 2;


	if (f == 0)
		nextmicros = micros();// if from stop

	//  rampup = m.rampup  ;
	c1=ytotalstep / m.dis;
	rampup = Math.floor(rampupmm * c1);
	rampdown = Math.floor(rampdownmm * c1);
	jramp1 = Math.floor(jramp1 * c1);
	jramp2 = Math.floor(jramp2 * c1);
	jrampb1 = Math.floor(jrampb1 * c1);
	jrampb2 = Math.floor(jrampb2 * c1);
	var c1=1/c1;
	acup*=c1;
	acdn*=c1;
	ajerk=tjerk*c1;
	
	// jerk stuff
	currac=0;
	if (rampup)currac=+1;

	if (rampdown){
		lastac=-1;
	} else {
		lastac=+1;
	}
	
	if (fe==0)lastac=0;
	
	
	
	jramp2 = rampup-jramp1-jramp2;
	
	rampdown2 = totalstep - rampup - rampdown;
	jrampb2 = rampdown-jrampb2-jrampb1;
	rampdown= rampdown2
	
	mctr2 = mcx[0] = mcx[1] = mcx[2] = mcx[3] = 0; //mctr >> 1;
	tail = t;
	/* 
		check the motion type
		
		
	
	*/
	//zprintf(PSTR("Last %f %f %f \n"), ff(px[0] / stepmmx[0]), ff(px[1] / stepmmx[0]), ff(px[2] / stepmmx[0]));
	//zprintf(PSTR("sx %d %d %d \n"), fi(sx[0]), fi(sx[1]), fi(sx[2]));
	//zprintf(PSTR("Status:%d \n"), fi(m.status));

	calculate_delta_steps();
	idlp=xInvSqrt(ta);
	acup1=0;
	acdn1=0;
	
	// laser
	return 1;
}

var GX=[0,0,0,0];
function bresenham(ix){
  if ((mcx[ix] -= bsdx[ix]) < 0) {
    cmd0 |=2<<ix;	
    mcx[ix] += totalstep;
	GX[ix]+=sx[ix];
	
	
  }
}
var lcinv=0.1;
function accele(a){
	//a is alreay multiplied by 2
	ta+=a;
}
function accele1(j){
	acup1+=j*lcinv;
	ta+=acup1;
}
function accele1a(j){
	acup1+=j*lcinv;
	ta+=acup1;
}
function accele2(j){
	acdn1+=j*lcinv;
	ta+=acdn1;
}
function accele2a(j){
	acdn1+=j*lcinv;
	ta+=acdn1;
}
var pcolor="black";
function coreloop1(){
  if (!m || (mctr <= 0)) {
    return 0;
  }


  if (cmdfull()) {
    //zprintf(PSTR("F\n"));
  } else   {
    cmd0 = 1; //step command

    bresenham(0);
    bresenham(1);
    bresenham(2);
    bresenham(3);
    // if rasterlen and e is change then read the new laser value
    // next speed
    cmd0 |= Math.round(dlp) << 5;
	//vv.push(stepdiv2/dlp);
	vv.push([Math.sqrt(ta),pcolor]);
    pushcmd();

    if (--mctr >0){
		var cf=0;
		lcinv=cinv;
		if ((rampup -= rampv) > 0) {
			if ((jramp1-=rampv)>0) {
				accele1(ajerk);
				pcolor="red";
			} else if ((jramp2-=rampv)<0){
				accele1a(-ajerk);
				pcolor="blue";
			} else {
				accele(acup);
				pcolor="black";
				acup1=acup;
			}
		    cf=1;
		} else if ((rampdown -= rampv) < 0) {
			if ((jrampb1-=rampv)>0) {
				accele2(-ajerk);
				pcolor="green";
			} else if ((jrampb2-=rampv)<0){
				accele2a(ajerk);
				pcolor="orange";
			} else {
				accele(acdn);
				pcolor="black";
				acdn1=acdn;
			}
			cf=1;
		} else {pcolor="pink";}

		//if (cf)
		{
		  if (ta < .1)ta = 0.1;
		  //if (ta > m.fn)ta = m.fn;
		  //zprintf(PSTR("%d\n"),fi(ta));
		  // if G0 update delay not every step to make the motor move faster
		  //if (m->status & 8) {
		}
		dlp=xInvSqrt(ta); //*F_SCALE;
		return 1;
	} return 0;
  }
  return 1;
}


// ===================================================================================
// MAIN CODE
// ===================================================================================

var demo="circle";

if (demo=="box"){

	addmove(30,20,10,0,0);
	addmove(13,20,30,0,0);
	addmove(12,0,20,0,0);
	addmove(8,0,0,0,0);
}
if (demo=="line"){
	addmove(20,20,10,0,0);
	//addmove(20,80,20,0,0);
}
if (demo=="circle"){
  for(var x=0;x<13;x++){
	var d=x/14.0*44/7;
    addmove(35, +Math.sin(d)*30, Math.cos(d)*30, 0, 0);
  }
//addmove(10, 0, 0, 0, 0);
}
ctx.beginPath();
ss=4.0/stepmm;
while (startmove()){
	// bresenham motion loop
	while (coreloop1()){
		x=200+GX[0]*ss;
		y=300+GX[1]*ss;
		
		ctx.lineTo(x,y);
		
	};
}
ctx.stroke();

var cmdly,cmcmd;
function decodecmd()
{
  if (cmdempty()) {

    return 0;

  }
  cmtail = nextbuffm(cmtail);
  var cmd = cmddelay[cmtail];
  cmcmd = cmd & 1;
  if (cmcmd) {
    cmbit = (cmd >> 1) & 15;
    cmdly = (cmd >> 5);
  } else {
    cmbit = (cmd >> 1) & 255;
    cmdly = 20;
  }
  return 1;
}

	
ff=0;
var tm=0;
function getf(i){
	var tm=0;
	var tv=0;
	var T=5;
	for (var j=-T;j<T;j++){
		var n=i+j;
		var v=-5;
		if (n>0 && n<vv.length)v=vv[n];
		tv+=v;
		tm++;
	}
	return max(0.2,tv/tm);
}
function getf2(i){
	var tm=0;
	var tv=0;
	var T=5;
	for (var j=-T;j<T;j++){
		var n=i+j;
		var v;
		if (n<0)v=1500000;
		else if (n>=ddd.length)v=1500000;
		else v=ddd[n];		
		tv+=v;
		tm++;
	}
	return tv/tm;
}


var GS=10;
var GY=500;
var GX=400;
ctx.beginPath();
ctx.strokeStyle="green";
for (var Y=0;Y<8;Y++){
	ctx.moveTo(GX,GY-Y*5*GS);
	//ctx.lineTo(1600,GY-Y*5*GS);
	ctx.fillText(Y*5,GX-30,GY-Y*5*GS);
}
ctx.stroke();
function drawF(intp,c,mask){
	ctx.beginPath();
	ctx.strokeStyle=c;
	x=GX;
	var lx=x;
	var ly=GY;
	var ni=0;
	cmtail=0;
	var stepd=CLOCKCONSTANT/stepmm;
	var ldly=0;
	while (decodecmd()){
		if (cmcmd){
			ldly+=cmdly;
			f=16*CLOCKCONSTANT/(cmdly*stepmm);
			if (intp)ff=getf(ni++); else ff=vv[ni++];
			f=ff[0]*GS;
			//f=stepd*GS/getf2(ni++);
			tm+=cmdly;
			ctx.strokeStyle=ff[1];
			ctx.beginPath();			
			ctx.moveTo(lx, ly);
			ctx.lineTo(x, GY-f);
			lx=x;ly=GY-f;
			x+=2*cmdly/10000;
			ctx.stroke();
		}// else 	ldly+=cmdly;
	}
}
//(vi*sqrt(2*(vf-vi)/jerk)+jerk*(sqrt(2*(vf-vi)/jerk)^3)/6)/x


drawF(0,"green",2);
drawF(1,"green",2);

console.log("Total time:%f:",tm/CLOCKCONSTANT);
console.log(ddd);

</script>
</body>
</html>
